package com.yswee.framework.widget.adapterview;

import java.util.ArrayList;

import com.yswee.framework.common.cache.image.ImageFetcher;
import com.yswee.framework.data.adapter.ILayoutViewAdapter;
import com.yswee.framework.data.adapter.LayoutViewAdapter;
import com.yswee.framework.widget.layoutview.ILayoutView;
import com.yswee.framework.widget.loading.IFooterBar;
import com.yswee.framework.widget.loading.MFooterBar;

import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.AbsListView;
import android.widget.HeaderViewListAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;

public abstract class MListView<T> extends com.yswee.framework.widget.swipemenu.SwipeMenuListView<T> {
	
	public static final int LISTVIEW_TYPE_VIEW = 0;
	public static final int MODE_LOADMORE_BOTTOM = 0x1;
	public static final int MODE_LOADMORE_TOP = 0x2;
	
	protected boolean mIsBusy;
	protected boolean mIsLastPage;
	protected IFooterBar mFooterView;
	
	protected ILayoutViewAdapter<T> mAdapter;
	protected OnScrollListener mScrollListener;
	
	protected OnScrollListener mScrollListenerProxy = new OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            // Pause fetcher to ensure smoother scrolling when flinging
            if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
                ImageFetcher.get().setPauseWork(true);
            } else {
            	ImageFetcher.get().setPauseWork(false);
            }
            if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
            	if (enabledLoadNextPage() && isReadyLoadData(false) && !mIsBusy && !mIsLastPage) {
            		boolean toedge = false;
            		if(getLoadMoreMode() == MODE_LOADMORE_BOTTOM) {
            			if(view.getLastVisiblePosition() == (view.getCount() - 1)) {
            				toedge = true;
            			}
            		} else {
            			if(view.getFirstVisiblePosition() == 0) {
            				toedge = true;
            			}
            		}
            		if(toedge) {
            			getNextPage();
            		}
            	}
            }
            if(mScrollListener != null) {
            	mScrollListener.onScrollStateChanged(view, scrollState);
            }
        }
        
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, 
        		int visibleItemCount, int totalItemCount) {
            if(mScrollListener != null) {
            	mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
            }
        }
    };
	
	public MListView(Context context) {
		this(context, null);
	}
	
	public MListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initializeListView();
		initializeAdapter();
	}
	
	public MListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initializeListView();
		initializeAdapter();
	}

	protected void initializeListView() {
		setCacheColorHint(Color.TRANSPARENT);
		setSelector(new ColorDrawable(Color.TRANSPARENT));
		setDividerHeight(0);
		setHorizontalScrollBarEnabled(false);
		setVerticalScrollBarEnabled(true);
		hideFadingEdge();
		if(getLoadMoreMode() == MODE_LOADMORE_TOP) {
			if(scrollToEdgeOnInit()) {
				setStackFromBottom(true);
				setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
			}
        }
		if(enabledLoadNextPage()) {
			mFooterView = getFooterView();
    		mFooterView.setVisibility(View.GONE);
    		setFooterDividersEnabled(false);
			if(specialFooterView()) {
				RelativeLayout footerview = new RelativeLayout(getContext());
		        footerview.addView((View)mFooterView, new RelativeLayout.LayoutParams(
		        		RelativeLayout.LayoutParams.MATCH_PARENT, 
		        		RelativeLayout.LayoutParams.WRAP_CONTENT));
		        if(getLoadMoreMode() == MODE_LOADMORE_BOTTOM) {
		        	addFooterView(footerview);
		        } else {
		        	addHeaderView(footerview);
		        }
			} else {;
		        if(getLoadMoreMode() == MODE_LOADMORE_BOTTOM) {
		        	addFooterView((View)mFooterView);
		        } else {
		        	addHeaderView((View)mFooterView);
		        }
			}
		}
		super.setOnScrollListener(mScrollListenerProxy);
		if(getListViewType() == LISTVIEW_TYPE_VIEW) {
			mAdapter = new LayoutViewAdapter<T>(mContext) {
				@Override
				public int getViewTypeCount() {
					return MListView.this.getViewTypeCount();
				}
	
				@Override
				protected int getLayoutResId(int position, T t, int itemViewType) {
					return MListView.this.getLayoutResId(position, t, itemViewType);
				}

				@Override
				protected ILayoutView<T> getLayoutView(int position, T t,
						int itemViewType) {
					return MListView.this.getLayoutView(position, t, itemViewType);
				}

				@Override
				protected boolean enabledSwipeMenu() {
					return MListView.this.enabledSwipeMenu();
				}

				@Override
				protected boolean enabledSwipeMenu(int position) {
					return MListView.this.enabledSwipeMenu(position);
				}

				@Override
				protected int getMenuResId(int position, T t, int itemViewType) {
					return MListView.this.getMenuResId(position, t, itemViewType);
				}

				@Override
				protected ILayoutView<T> getLayoutMenu(int position, T t, int itemViewType) {
					return MListView.this.getLayoutMenu(position, t, itemViewType);
				}

				@Override
				protected Interpolator getOpenInterpolator() {
					return MListView.this.getOpenInterpolator();
				}

				@Override
				protected Interpolator getCloseInterpolator() {
					return MListView.this.getCloseInterpolator();
				}
			};
		} else {
			onInvalidParam("getListViewType() return invalid value");
		}
	}
	
	/**
	 * 初始化adapter
	 */
	protected void initializeAdapter() {
		setAdapter(mAdapter);
	}

	/*=============== protected method ====================*/
	/**
	 * 设置是否http请求中
	 * @param value
	 */
	protected void setIsBusy(boolean value) {
		mIsBusy = value;
	}
	
	/**
	 * 是否http请求中
	 * @param value
	 */
	public boolean getIsBusy() {
		return mIsBusy;
	}
	
	/**
	 * 参数错误
	 * @param msg
	 */
	protected void onInvalidParam(String msg) {
		throw new RuntimeException(msg);
	}
	
	/**
	 * 取得下一页的模式（触底、触顶加载下一页）
	 * @return
	 */
	protected int getLoadMoreMode() {
		return MODE_LOADMORE_BOTTOM;
	}
	
	/**
	 * 初始化时是否滑动至顶部或底部
	 * @return
	 */
	protected boolean scrollToEdgeOnInit() {
		return true;
	}
	
	/**
	 * 显示Footer
	 * @param isloading true : 显示加载中  false ： 显示已加载全部
	 */
	protected void showFooterView(boolean isloading) {
    	if(mFooterView != null) {
    		mFooterView.setVisibility(View.VISIBLE);
    		if(isloading) {
    			mFooterView.showLoading();
    			if(getLoadMoreMode() == MODE_LOADMORE_BOTTOM) {
    				scrollToBottom();
    			} else {
    				scrollToTop();
    			}
    		} else {
    			mFooterView.showLoadAll();
    		}
    	}
    }
    
	/**
	 * 隐藏Footer
	 */
	protected void hideFooterView() {
    	if(mFooterView != null) {
    		mFooterView.setVisibility(View.GONE);
    	}
    }
	
	/**
	 * 开始加载数据
	 * @param isFirstPage 是否请求的第一页数据
	 */
	protected void onBeginLoad(boolean isFirstPage) {
		mIsBusy = true;
		if(isFirstPage) {
			mIsLastPage = false;
			hideFooterView();
		} else {
	        setFooterDividersEnabled(true);
			showFooterView(true);
		}
	}

	/**
	 * 结束加载数据
	 * @param isLastPage 是否是最后一页数据
	 */
	protected void onEndLoad(boolean isLastPage) {
		mIsBusy = false;
		if(isLastPage) {
			mIsLastPage = true;
			showFooterView(false);
			setFooterDividersEnabled(true);
		} else {
			hideFooterView();
			setFooterDividersEnabled(false);
		}
	}
	
	/**
	 * ListView的模板数
	 * @return
	 */
	protected int getViewTypeCount() {
		return 1;
	}
    
	/**
	 * 是否允许触底加载下一页
	 * @return
	 */
	protected boolean enabledLoadNextPage() {
		return true;
	}
	
	/**
	 * 是否准备好加载数据
	 * @param isFirstPage
	 * @return
	 */
	public boolean isReadyLoadData(boolean isFirstPage) {
		return true;
	}
    
	/**
	 * ListView的加载方式
	 * LISTVIEW_TYPE_VIEW  (必须override createLayoutView 方法）
	 * LISTVIEW_TYPE_DATABINDING （必须override getLayoutResId/getLayoutView 方法）
	 * @return
	 */
	protected abstract int getListViewType();
    
	/**
	 * 是否采用ViewGroup包裹footer的方式（这样的话，footer隐藏的时候不会占位）
	 * @return
	 */
	protected boolean specialFooterView() {
		return false;
	}
	
	/**
	 * 取得Footer
	 * @return
	 */
	protected IFooterBar getFooterView() {
		return new MFooterBar(mContext);
	}
	
	/*=============== public method ====================*/
	/**
	 * 请求第一页数据（需自己实现获取数据）
	 */
	public void getFirstPage() {
		if (mIsBusy) {
			return;
		}
		if (!isReadyLoadData(true)) {
			return;
		}
		onBeginLoad(true);
	}
	
	/**
	 * 请求下一页数据（需自己实现获取数据）
	 */
	public void getNextPage() {
		if (mIsBusy) {
			return;
		}
		if (!isReadyLoadData(false)) {
			return;
		}
		onBeginLoad(false);
	}

	/**
	 * 设置数据源
	 * @param data
	 */
	public void setDataSource(ArrayList<T> data) {
		mAdapter.setDataSource(data);
		mAdapter.notifyDataSetChanged();
	}

	/**
	 * 取得数据源
	 * @return
	 */
	public ArrayList<T> getDataSource() {
		if(mAdapter != null)
			return mAdapter.getDataSource();
		else
			return null;
	}

	/**
	 * 通知adapter刷新UI
	 */
	public void notifyDataSetChanged() {
		if(mAdapter != null)
			mAdapter.notifyDataSetChanged();
	}
	
	/**
	 * 获取数据源的条数
	 */
	public int getAdapterCount() {
		ListAdapter adapter = getAdapter();
		if(adapter != null) {
			if(adapter instanceof HeaderViewListAdapter) {
				adapter = ((HeaderViewListAdapter) adapter).getWrappedAdapter(); 
			}
			return adapter.getCount();
		}
		return 0;
	}
	
	/**
	 * 本地数据源增加数据
	 * @param t
	 * @return
	 */
	public boolean addData(T t) {
		ArrayList<T> datas = getDataSource();
		if(datas != null) {
			datas.add(t);
			setDataSource(datas);
			return true;
		}
		return false;
	}
	
	/**
	 * 本地数据源增加数据
	 * @param index
	 * @param t
	 * @return
	 */
	public boolean addData(int index, T t) {
		ArrayList<T> datas = getDataSource();
		if(datas != null) {
			datas.add(index, t);
			setDataSource(datas);
			return true;
		}
		return false;
	}
	
	/**
	 * 本地数据源移除数据
	 * @param t
	 * @return
	 */
	public boolean removeData(T t) {
		ArrayList<T> datas = getDataSource();
		if(datas != null) {
			boolean result = datas.remove(t);
			setDataSource(datas);
			return result;
		}
		return false;
	}
	
	/**
	 * 本地数据源移除数据
	 * @param index
	 * @return
	 */
	public T removeData(int index) {
		ArrayList<T> datas = getDataSource();
		if(datas != null) {
			T t = datas.remove(index);
			setDataSource(datas);
			return t;
		}
		return null;
	}
	
	/**
	 * 本地数据源移除全部数据
	 * @return
	 */
	public boolean clearData() {
		ArrayList<T> datas = getDataSource();
		if(datas != null) {
			datas.clear();
			setDataSource(datas);
			return true;
		}
		return false;
	}
	
	@Override
	public void addHeaderView(View v, Object data, boolean isSelectable) {
		if(getAdapter() != null) {
			setAdapter(null);
			super.addHeaderView(v, data, isSelectable);
			setAdapter(mAdapter);
		} else {
			super.addHeaderView(v, data, isSelectable);
		}
	}
	
	@Override
	public void setOnScrollListener(OnScrollListener l) {
		mScrollListener = l;
	}

	protected int getLayoutResId(int position, T t, int itemViewType) {
		return 0;
	}
	
	protected ILayoutView<T> getLayoutView(int position, T t, int itemViewType) {
		return null;
	}
	
}
